package com.baitiaojun.repeatsubmit.core.interceptor.impl;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baitiaojun.common.constants.Constants;
import com.baitiaojun.common.enums.impl.HttpMethodEnums;
import com.baitiaojun.common.utils.object.ObjectUtils;
import com.baitiaojun.common.utils.string.StringUtils;
import com.baitiaojun.redis.core.support.RedisSupport;
import com.baitiaojun.repeatsubmit.core.interceptor.RepeatSubmitInterceptor;
import com.baitiaojun.web.core.utils.WebUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Component("repeatSubmitDefaultRule")
@Slf4j
public class RepeatSubmitInterceptorImpl implements RepeatSubmitInterceptor {

    private static final String REQ_PARAM = "reqParam";

    private static final String REQ_TIME = "reqTime";

    public static final String REQ_URI = "reqUri";

    @Autowired
    private RedisSupport redisSupport;

    @Override
    public boolean isRepeatable(Long interval, String tokenSign, HttpServletRequest request) {
        //创建缓存key
        String key = request.getRequestURI();
        if (StringUtils.isNotEmpty(tokenSign)) {
            key += request.getHeader(tokenSign); //根据tokenSign获取token
        }
        //获取请求参数
        String method = request.getMethod();
        String params;
        if (HttpMethodEnums.POST.getName().equalsIgnoreCase(method) ||
                HttpMethodEnums.PUT.getName().equalsIgnoreCase(method)) {
            params = WebUtils.getJsonStr(request);
        } else {
            params = JSONObject.toJSONString(request.getParameterMap());
        }
        Object object = redisSupport.getValue(Constants.REPEAT_SUBMIT_KEY, key);
        if (ObjectUtil.isNull(object)) {
            //创建缓存数据, 用参数和时间作为重复提交的判断条件
            Map<String, Object> data = MapUtil.ofEntries(
                    MapUtil.entry(REQ_URI, key),
                    MapUtil.entry(REQ_PARAM, params),
                    MapUtil.entry(REQ_TIME, System.currentTimeMillis()));
            //当前请求添加到缓存
            redisSupport.addValue(Constants.REPEAT_SUBMIT_KEY, key, data, interval, TimeUnit.MILLISECONDS);
        } else {
            //解析缓存结果进行规则比较
            Map<String, Object> map = ObjectUtils.toMap(object);
            String reqUri = String.valueOf(map.get(REQ_URI));
            if (reqUri.equalsIgnoreCase(key)) {
                String reqParam = String.valueOf(map.get(REQ_PARAM));
                String reqTime = String.valueOf(map.get(REQ_TIME));
                boolean time = (System.currentTimeMillis() - Long.parseLong(reqTime)) <= interval;
                boolean param = reqParam.equals(params);
                return time && param;
            }
        }
        return false;
    }
}
